#include "BaseSousSel.h"

#include <QtGui/QButtonGroup>
#include <QtGui/QGroupBox>
#include <QtGui/QGridLayout>
#include <QtGui/QVBoxLayout>
#include <QtGui/QHBoxLayout>
#include <QtGui/QCheckBox>
#include <QtGui/QPushButton>

using namespace std;

DebugLevelType BaseSousSel::gestionListe( BLANK );

/**
 * Constructeur permettant de sélectionner plusieurs objets parmi une
 * liste. Ici on donne les noms par un vector.
 *
 * @param fenNom nomN du widget.
 * @param nbr nombre d'objets.
 * @param noms contient la liste de noms.
 * @param titre nom du groupe d'objets.
 * @param parent widget parent de l'objet (orphelin par défaut)..
 */
BaseSousSel::BaseSousSel(const QString& fenNom, const unsigned int& nbr,
			 const vector<string>& noms,
			 const string& titre, QWidget *parent)
  : BaseDialog( fenNom, parent ), dimension( nbr )
{
  boite = new QGroupBox( QString::fromUtf8(titre.c_str()), this );

  groupe = new QButtonGroup( this );

  groupe -> setExclusive( false );

  QGridLayout *boiteLayout = new QGridLayout( boite );

  for (unsigned int i(0); i < dimension; i++)
    {
      groupe -> addButton( new QCheckBox( trUtf8( noms[i].c_str()), this ), i );
      boiteLayout -> addWidget( groupe -> button( i ), i % 10, i/10 );
    }

  boite -> setLayout( boiteLayout );
}

/**
 * Constructeur permettant de sélectionner plusieurs objets parmi une
 * liste. La liste est ici donnée par le nombre d'élément et un
 * pointeur sur le premier élément.
 *
 * @param fenNom nomN du widget.
 * @param nbr nombre d'objets.
 * @param noms pointeur sur le premier élément de la liste de noms.
 * @param titre nom du groupe d'objets.
 * @param parent widget parent de l'objet, (par défaut, pas de
 * parent).
 */
BaseSousSel::BaseSousSel(const QString& fenNom, const unsigned int& nbr, 
			 const string* noms, const string& titre,
			 QWidget *parent)
  : BaseDialog( fenNom, parent ), dimension( nbr )
{
  boite = new QGroupBox( QString::fromUtf8(titre.c_str()), this );

  groupe = new QButtonGroup( this );

  groupe -> setExclusive( false );

  QGridLayout *boiteLayout = new QGridLayout( boite );

  for (unsigned int i(0); i < dimension; i++)
    {
      groupe -> addButton( new QCheckBox( trUtf8( (*(noms + i)).c_str()), this ), i );
      boiteLayout -> addWidget( groupe -> button( i ), i % 10, i/10 );
    }

  boite -> setLayout( boiteLayout );
}


/**
 * Constructeur permettant de sélectionner plusieurs objets parmi une
 * liste. La liste est ici donnée par le nombre d'élément et un
 * pointeur sur le premier élément. Certains éléments doivent être
 * désactivés dans le choix, car ils sont déjà sélectionnés.
 *
 * @param fenNom nomN du widget.
 * @param nbr nombre d'objets.
 * @param noms pointeur sur le premier élément de la liste de noms.
 * @param deja conteneur des objets déjà connus.
 * @param titre nom du groupe d'objets.
 * @param parent widget parent de l'objet, (par défaut, pas de parent).
 */
BaseSousSel::BaseSousSel(const QString& fenNom, const unsigned int& nbr,
			 const string* noms, const vector<bool>& deja,
			 const string& titre, QWidget *parent)
  : BaseDialog( fenNom, parent ), dimension( nbr )
{
  boite = new QGroupBox( QString::fromUtf8(titre.c_str()), this );

  groupe = new QButtonGroup( this );

  groupe -> setExclusive( false );

  QGridLayout *boiteLayout = new QGridLayout( boite );

  for (unsigned int i(0); i < dimension; i++)
    {
      groupe -> addButton( new QCheckBox( trUtf8( (*(noms + i)).c_str()), this ), i );
      boiteLayout -> addWidget( groupe -> button( i ), i % 10, i/10 );
      if (deja[i])
	{
	  groupe -> button(i) -> setChecked( true );
	  groupe -> button(i) -> setEnabled( false );
	}
    }

  boite -> setLayout( boiteLayout );
}

/**
 * Constructeur permettant de sélectionner plusieurs objets parmi une
 * liste. Ici on donne les noms par un vector. Certains éléments
 * doivent être désactivés dans le choix, car ils sont déjà
 * sélectionnés.
 *
 * @param fenNom nomN du widget.
 * @param nbr nombre d'objets.
 * @param noms contient la liste de noms.
 * @param deja conteneur des objets déjà connus.
 * @param titre nom du groupe d'objets.
 * @param parent widget parent de l'objet, (par défaut, pas de parent).
 */
BaseSousSel::BaseSousSel(const QString& fenNom, const unsigned int& nbr,
			 const vector<string>& noms,const vector<bool>& deja,
			 const string& titre, QWidget *parent)
: BaseDialog( fenNom, parent ), dimension( nbr )
{
  boite = new QGroupBox( QString::fromUtf8(titre.c_str()), this );

  groupe = new QButtonGroup( this );

  groupe -> setExclusive( false );

  QGridLayout *boiteLayout = new QGridLayout( boite );

  for (unsigned int i(0); i < dimension; i++)
    {
      groupe -> addButton( new QCheckBox( trUtf8( noms[i].c_str()), this ), i );
      boiteLayout -> addWidget( groupe -> button( i ), i % 10, i/10 );
      if (deja[i])
	{
	  groupe -> button(i) -> setChecked( true );
	  groupe -> button(i) -> setEnabled( false );
	}
    }

  boite -> setLayout( boiteLayout );
}

/**
 * Constructeur de copie. On doit ici faire attention à bien gérer les
 * différentes possibilités (choix exclusif, choix déjà effectué).
 *
 * @param sousSel instance de BaseSousSel à dupliquer.
 */
BaseSousSel::BaseSousSel(const BaseSousSel& sousSel)
  : BaseDialog( sousSel ), dimension( sousSel.dimension )
{
  boite = new QGroupBox( sousSel.boite -> title(), this );

  groupe = new QButtonGroup( this );

  groupe -> setExclusive( sousSel.groupe -> exclusive() );

  QGridLayout *boiteLayout = new QGridLayout( boite );

  QCheckBox* ptrButton;

  for (unsigned int i(0); i < dimension; i++)
    {
      ptrButton = static_cast< QCheckBox* >( sousSel.groupe -> button( i ) );
      groupe -> addButton( new QCheckBox( ptrButton -> text(), this ), i );
      boiteLayout -> addWidget( groupe -> button( i ), i % 10, i/10 );
      if ( ! static_cast< QCheckBox* >( sousSel.groupe -> button( i ) )
	   -> isEnabled() )
	{
	  groupe -> button(i) -> setChecked( true );
	  groupe -> button(i) -> setEnabled( false );
	}
    }

  boite -> setLayout( boiteLayout );
}

/**
 * Destructeur, ne fait rien de spécial. Est déclaré virtual pour
 * assurer une destruction propre des objets.
 */
BaseSousSel::~BaseSousSel()
{}

/**
 * Effectue la sélection et rempli le conteneur avec les valeurs des
 * choix effectués.
 *
 * @param vec conteneur des valeurs sélectionnées. Est rempli lors de
 * la fermeture du QDialog. Pour un choix exclusif, l'information est
 * également présente dans le StatusCode.
 * @return StatusCode \e true si choix validé, \e false sinon. Si le
 * choix est exclusif, le numéro choisi est stocké dans valeur(). La
 * méthode message() permet d'avoir la descritpion du type de choix
 * effectué.
 */
StatusCode BaseSousSel::selectionFaite(vector<unsigned int>& vec)
{
  this -> exec();

  if ( OK )
    {
      for (unsigned int i(0); i < dimension; i++)
	{
	  if (groupe -> button(i) -> isChecked() &&
	      groupe -> button(i) -> isEnabled())
	    vec.push_back(i);
	}

      if ( groupe -> exclusive() )
	return StatusCode( OK, vec.back(), 0, "Choix unique" );
      else
	return StatusCode( OK, 0, 0, "Choix multiple" );
    }
  else
    return StatusCode( OK, 0, 0, "Choix annulé" );
}

/**
 * Sert à rendre la sélection exclusive, si par exemple on veut
 * choisir une catégorie de compétence plutôt que des compétences. Par
 * défaut le choix n'est pas exclusif.
 *
 * @param etat booléen pour choix exclusif.
 */
void BaseSousSel::setExclusif(const bool& etat)
{
  groupe -> setExclusive( etat );
}

/**
 * Permet de modifier la valeur de BaseSousSel::gestionListe.
 *
 * @param level nouvelle valeur de BaseSousSel::gestionListe.
 */
void BaseSousSel::setLevel(const DebugLevelType& level)
{
  gestionListe = level;
}
